package net.sh.dpinfrastructure.support.spring.configuration;

import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.alibaba.druid.pool.DruidDataSource;

import net.sh.dpinfrastructure.config.DPConfig;
import net.sh.dpinfrastructure.sql.DPJdbcTemplate;
import net.sh.dpinfrastructure.sql.DPSql;

/**
 * 
 * jdbc 配置
 * 
 * @author shaohui 
 * @date: 2016年7月29日下午10:51:30 <br/> 
 * @version  
 * @since JDK 1.8
 */
@Configuration
@Import(DPConfigConfiguration.class)
@EnableTransactionManagement
public class DPJDBCConfiguration {
    
    /**
     * 默认初始连接数
     */
    public static final int DEFAULT_SQL_DATASOURCE_INITIAL_SIZE = 10;
    
    /**
     * 默认最小空闲连接数
     */
    public static final int DEFAULT_SQL_DATASOURCE_MIN_IDLE = 10;
    
    /**
     * 默认最大活动连接数
     */
    public static final int DEFAULT_SQL_DATASOURCE_MAX_ACTIVE = 50;
    
    /**
     * 默认连接超时时间
     */
    public static final long DEFAULT_SQL_DATASOURCE_MAX_WAIT = 10 * 1000;
    
    /**
     * 默认多久（ms）检测需要关闭的空闲连接
     */
    public static final long DEFAULT_SQL_DATASOURCE_TIME_BETWEEN_EVICTION_RUNS_MILLIS = 10 * 1000;
    
    /**
     * 连接在池中默认最小生存时间
     */
    public static final long DEFAULT_SQL_DATASOURCE_MIN_EVICTABLE_IDLE_TIME_MILLIS = 10 * 1000;
    
    /**
     * 用来检测连接是否有效的默认sql
     */
    public static final String DEFAULT_SQL_DATASOURCE_VALIDATION_QUERY = "SELECT 'a'";
    
    /**
     * 是否检测空闲连接有效
     */
    public static final boolean DEFAULT_SQL_DATASOURCE_TEST_WHILE_IDLE = true;
    
    /**
     * 获取连接时是否检测连接有效
     */
    public static final boolean DEFAULT_SQL_DATASOURCE_TEST_ON_BORROW = false;
    
    /**
     * 归还连接时是否检测连接有效
     */
    public static final boolean DEFAULT_SQL_DATASOURCE_TEST_ON_RETURN = false;
    
    /**
     * 是否开启pscache
     */
    public static final boolean DEFAULT_SQL_DATASOURCE_POOL_PREPARED_STATEMENTS = false;
    
    /**
     * 开启pscache后每个连接上cache大小
     */
    public static final int DEFAULT_SQL_DATASOURCE_MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE = 20;

    /**
     * 
     * 配置数据源 <br/> 
     * 
     * @return
     *
     * @author shaohui
     * @date 2016年7月29日下午10:52:32
     * @since JDK 1.8
     */
    @Bean(destroyMethod = "close", initMethod = "init")
    public DataSource getDataSource(DPConfig config) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(config.get("sql.driver"));
        dataSource.setUrl(config.get("sql.url"));
        dataSource.setUsername(config.get("sql.username"));
        dataSource.setPassword(config.get("sql.password"));
        dataSource.setInitialSize(config.getIntValue("sql.datasource.initialSize", DEFAULT_SQL_DATASOURCE_INITIAL_SIZE));
        dataSource.setMinIdle(config.getIntValue("sql.datasource.minIdle", DEFAULT_SQL_DATASOURCE_MIN_IDLE));
        dataSource.setMaxActive(config.getIntValue("sql.datasource.maxActive", DEFAULT_SQL_DATASOURCE_MAX_ACTIVE));
        dataSource.setMaxWait(config.getLongValue("sql.datasource.maxWait", DEFAULT_SQL_DATASOURCE_MAX_WAIT));
        dataSource.setTimeBetweenEvictionRunsMillis(config.getLongValue("sql.datasource.timeBetweenEvictionRunsMillis", DEFAULT_SQL_DATASOURCE_MIN_EVICTABLE_IDLE_TIME_MILLIS));
        dataSource.setValidationQuery(config.get("sql.datasource.validationQuery", DEFAULT_SQL_DATASOURCE_VALIDATION_QUERY));
        dataSource.setTestWhileIdle(config.getBoolValue("sql.datasource.testWhileIdle", DEFAULT_SQL_DATASOURCE_TEST_WHILE_IDLE));
        dataSource.setTestOnBorrow(config.getBoolValue("sql.datasource.testOnBorrow", DEFAULT_SQL_DATASOURCE_TEST_ON_BORROW));
        dataSource.setTestOnReturn(config.getBoolValue("sql.datasource.testOnReturn", DEFAULT_SQL_DATASOURCE_TEST_ON_RETURN));
        dataSource.setPoolPreparedStatements(config.getBoolValue("sql.datesource.poolPreparedStatements", DEFAULT_SQL_DATASOURCE_POOL_PREPARED_STATEMENTS));
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(config.getIntValue("sql.datesource.maxPoolPreparedStatementPerConnectionSize", DEFAULT_SQL_DATASOURCE_MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE));
        return dataSource;
    }
    
    /**
     * 
     * 配置事务管理器
     * 
     * @param dataSource
     * @return
     *
     * @author shaohui
     * @date 2016年7月30日上午11:17:06
     * @since JDK 1.8
     */
    @Bean
    public PlatformTransactionManager getTransactionManager(DataSource dataSource) {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }
    
    /**
     * 
     * 配置事务管理器
     * 
     * @param dataSource
     * @return
     *
     * @author shaohui
     * @date 2016年7月30日上午11:19:15
     * @since JDK 1.8
     */
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
        if (dataSource == null) {
            return null;
        }
        JdbcTemplate jdbcTemplate = new DPJdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }
    
    /**
     * 
     * 配置sql操作封装类
     *
     * @param dataSource
     * @param logger
     * @return
     * 
     * @author shaohui
     * @date 2016年8月8日 下午2:36:10
     */
    @Bean
    public DPSql getDPSql(DataSource dataSource) {
        if (dataSource == null) {
            return null;
        }
        return new DPSql(dataSource);
    }
}
